
#include "delay.h"
#include "printf.h"
#include <stdbool.h>
#include <stdio.h>
#include <stm32f10x.h>

typedef unsigned short u16;

void GPIOA_0_to_3_init() {
    GPIO_InitTypeDef def;

    def.GPIO_Mode = GPIO_Mode_Out_PP;
    def.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    def.GPIO_Speed = GPIO_Speed_50MHz;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_Init(GPIOA, &def);

    // DO
    def.GPIO_Pin = GPIO_Pin_2;
    def.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &def);
    // AO
    def.GPIO_Pin = GPIO_Pin_3;
    def.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &def);

    // VCC
    GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
    // GND
    GPIO_WriteBit(GPIOA, GPIO_Pin_1, Bit_RESET);
}

void ADC1_init() {
    ADC_InitTypeDef ADC_initial;

    ADC_initial.ADC_Mode = ADC_Mode_Independent;
    ADC_initial.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_initial.ADC_ContinuousConvMode = ENABLE;
    ADC_initial.ADC_NbrOfChannel = 1;
    ADC_initial.ADC_ScanConvMode = DISABLE;
    ADC_initial.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    ADC_Init(ADC1, &ADC_initial);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_55Cycles5);

    ADC_ResetCalibration(ADC1);
    printf("%d\r\n", __LINE__);
    // wait
    while (ADC_GetResetCalibrationStatus(ADC1) == RESET)
        ;

    ADC_StartCalibration(ADC1);

    printf("%d\r\n", __LINE__);
    // wait
    while (ADC_GetCalibrationStatus(ADC1) == SET)
        ;
    printf("%d\r\n", __LINE__);

    ADC_Cmd(ADC1, ENABLE);

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

int ADC1_get_value() {

    if (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == SET) {

        int v = ADC_GetConversionValue(ADC1);
        ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
        return v;
    }

    return 0;
}

int main() {

    printf_init(9600);
    delay_init();

    delay_s(10);

    GPIOA_0_to_3_init();
    ADC1_init();

    while (true) {

        printf("main running\r\n");

        printf("GPIOA = %#X\r\n", GPIO_ReadInputData(GPIOA));

        int d = ADC1_get_value();
        printf("ADC1 Data:%d\r\n", d);

        printf("U = %f (V)\r\n", d * 3.3 / 4096);

        delay_s(2);
    }

    return 0;
}
